local VERSION = tonumber(("$Revision: 45259 $"):match("%d+"))

local _G = getfenv(0)

local L = AceLibrary("AceLocale-2.2"):new("AuldLangSyne_GuildList")
local guild = LibStub("LibGuild-1.0")

local AuldLangSyne = AuldLangSyne
local GuildList, Info
if AuldLangSyne then
	GuildList = AuldLangSyne:NewModule("GuildList", "AceEvent-2.0", "AceHook-2.1", "AceConsole-2.0")
	if AuldLangSyne.revision < VERSION then
		AuldLangSyne.version = "r" .. VERSION
		AuldLangSyne.revision = VERSION
		AuldLangSyne.date = ("$Date: 2007-07-29 22:02:53 -0700 (Sun, 29 Jul 2007) $"):match("%d%d%d%d%-%d%d%-%d%d")
	end
	if AuldLangSyne:HasModule("Info") then
		Info = AuldLangSyne:GetModule("Info")
	end
else
	GuildList = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0", "AceHook-2.1", "AceConsole-2.0", "AceDB-2.0")
	AuldLangSyne_GuildList = GuildList -- since this isn't a module in this branch, global for access
	Info = AuldLangSyne_Info
end

function GuildList:OnInitialize(name)
	local profiledefaults = {
		name = "[name:class]",
		area = "[area]",
		level = "[level:level]",
		class = "[class:class]",
		coloronline = true,
		coloroffline = true,
		fadeoffline = 0.5,
	}
	if AuldLangSyne then
		self.db = AuldLangSyne:AcquireDBNamespace("GuildList")
		AuldLangSyne:RegisterDefaults("GuildList", "profile", profiledefaults)
	else
		self:RegisterDB("AuldLangSyneGuildListDB")
		self:RegisterDefaults("profile", profiledefaults)
	end
	
	self.menu = {
		handler = GuildList,
		type = "group",
		name = L["Guild List"], desc = L["Choose what information to display"],
		args = {
			columns = {
				name = L["Columns"], type = "group",
				desc = L["Settings for each column"],
				args = {
					name = {
						name = L["Name"], type = "text",
						desc = L["Name"],
						usage = L["See documentation at: http://www.wowace.com/wiki/AuldLangSyne"],
						get = function() return self.db.profile.name end,
						set = function(t) self.db.profile.name = t; self:GuildStatus_Update() end,
					},
					area = {
						name = L["Area"], type = "text",
						desc = L["Area"],
						usage = L["See documentation at: http://www.wowace.com/wiki/AuldLangSyne"],
						get = function() return self.db.profile.area end,
						set = function(t) self.db.profile.area = t; self:GuildStatus_Update() end,
					},
					level = {
						name = L["Level"], type = "text",
						desc = L["Level"],
						usage = L["See documentation at: http://www.wowace.com/wiki/AuldLangSyne"],
						get = function() return self.db.profile.level end,
						set = function(t) self.db.profile.level = t; self:GuildStatus_Update() end,
					},
					class = {
						name = L["Class"], type = "text",
						desc = L["Class"],
						usage = L["See documentation at: http://www.wowace.com/wiki/AuldLangSyne"],
						get = function() return self.db.profile.class end,
						set = function(t) self.db.profile.class = t; self:GuildStatus_Update() end,
					},
				},
			},
			color = {
				type = "group",
				name = L["Color"],
				desc = L["Color"],
				args = {
					online = {
						name = L["Online"], type = "toggle",
						desc = L["Color online friends, according to their tags."],
						get = function() return self.db.profile.coloronline end,
						set = function(t) self.db.profile.coloronline = t; self:GuildStatus_Update() end,
					},
					offline = {
						name = L["Offline"], type = "toggle",
						desc = L["Color offline friends, according to their tags."],
						get = function() return self.db.profile.coloroffline end,
						set = function(t) self.db.profile.coloroffline = t; self:GuildStatus_Update() end,
					},
					fade = {
						name = L["Fade offline"], type = "range",
						desc = L["Fade colors for offline friends to this %age of their base value."],
						min = 0, max = 1, step = 0.05, isPercent = true,
						get = function() return self.db.profile.fadeoffline end,
						set = function(t) self.db.profile.fadeoffline = t; self:GuildStatus_Update() end,
					},
				},
			},
		},
	}
	
	self:RegisterChatCommand({'/friendlist', '/alsfriendlist',}, self.menu)
	
	--Stolen from AceDB.
	local _,race = UnitRace("player")
	if race == "Orc" or race == "Scourge" or race == "Troll" or race == "Tauren" or race == "BloodElf" then
		self.faction = "0"
	else
		self.faction = "1"
	end
end

function GuildList:OnEnable(first)
	guild.RegisterCallback(self, "Update", "GuildStatus_Update")
	self:SecureHook("GuildStatus_Update")
end

------------------------------------------------------------------------
-- Friend info display
------------------------------------------------------------------------

do
	local colors = {
		["class"] = function(name)
				return guild:GetClassColor(name)
			end,
		["level"] = function(name)
				local level = guild:GetLevel(name)
				if level then
					local c = GetDifficultyColor(level)
					return c.r, c.g, c.b
				end
				return 1,1,1
			end,
		["sex"] = function(name)
				local sex = Info and Info.db.realm[name] and Info.db.realm[name].sex
				if sex == MALE then
					return 0.56, 0.69, 0.94
				elseif sex == FEMALE then
					return 0.94, 0.56, 0.76
				end
				return 1, 1, 1
			end,
		-- And some static colors
		["gold"] = function(name) return 1, 0.78, 0 end, -- this is the "default" blizzard-gold color
		["red"] = function(name) return 1, 0, 0 end,
		["green"] = function(name) return 0, 1, 0 end,
		["blue"] = function(name) return 0, 0, 1 end,
		["white"] = function(name) return 1, 1, 1 end,
		["black"] = function(name) return 0, 0, 0 end,
		["grey"] = function(name) return 0.5, 0.5, 0.5 end,
	}
	local colorformat = "|cff%.2x%.2x%.2x%s|r"
	local function colorify(name, colortype, s)
		if (not s) or s=='' then return '' end
		local online = guild:IsMemberOnline(name)
		if (online and GuildList.db.profile.coloronline) or ((not online) and GuildList.db.profile.coloroffline) then
			local r, g, b = 1, 1, 1
			if colortype then
				if colors[colortype] then
					r, g, b = colors[colortype](name)
				else
					local hexr, hexg, hexb = colortype:match("c(%x%x)(%x%x)(%x%x)")
					if hexr then
						r, g, b = tonumber(hexr, 16)/255, tonumber(hexg, 16)/255, tonumber(hexb, 16)/255
					end
				end
			end
			if not online then
				local fade = GuildList.db.profile.fadeoffline
				r, g, b = r*fade, g*fade, b*fade
			end
			return colorformat:format(r*255, g*255, b*255, s)
		else
			if online then
				return s
			else
				local fade = GuildList.db.profile.fadeoffline
				return colorformat:format(255*fade, 255*fade, 255*fade, s)
			end
		end
	end
	local subs = {
		["name"] = function(name, modifier) return colorify(name, modifier, name) end,
		["class"] = function(name, modifier) return colorify(name, modifier, guild:GetClass(name)) end,
		["level"] = function(name, modifier) return colorify(name, modifier, guild:GetLevel(name)) end,
		["race"] = function(name, modifier) return colorify(name, modifier, Info and Info.db.realm[name] and Info.db.realm[name].race) end,
		["sex"] = function(name, modifier) return colorify(name, modifier, Info and Info.db.realm[name] and Info.db.realm[name].sex) end,
		["pvprank"] = function(name, modifier) return colorify(name, modifier, Info and Info.db.realm[name] and Info.db.realm[name].rank and GuildList:GetRankName(Info.db.realm[name].rank, Info.db.realm[name].sex)) end,
		["pvpranknum"] = function(name, modifier) return colorify(name, modifier, Info and Info.db.realm[name] and Info.db.realm[name].rank and tostring(Info.db.realm[name].rank - 4)) end,
		["guild"] = function(name, modifier) return colorify(name, modifier, Info and Info.db.realm[name] and Info.db.realm[name].guild and ('<'..Info.db.realm[name].guild..'>')) end,
		["guildrank"] = function(name, modifier) return colorify(name, modifier, Info and Info.db.realm[name] and Info.db.realm[name].guildRank) end,
		["area"] = function(name, modifier) return colorify(name, modifier, guild:GetZone(name)~=UNKNOWN and guild:GetZone(name) or '') end,
		["status"] = function(name, modifier) return colorify(name, modifier, guild:IsMemberOnline(name) and (guild:GetStatus(name) or '') or GuildList:HowLongAgo(guild:GetSecondsOffline())) end,
	}
	local tagpattern = "%[([^:%]]+):?([^%]]*)%]"
	local current_member
	local function tagreplace(tag, modifier)
		if subs[tag] then
			return subs[tag](current_member, modifier)
		else
			return colorify(current_member, modifier, tag)
		end
	end
	function GuildList:GuildStatus_Update()
		if FriendsFrame:IsVisible() and FriendsFrame.selectedTab == 3 then
			local guildOffset = FauxScrollFrame_GetOffset(GuildListScrollFrame)
			local numGuildMembers = GetNumGuildMembers()
			local n = GUILDMEMBERS_TO_DISPLAY

			if numGuildMembers < GUILDMEMBERS_TO_DISPLAY then n = numGuildMembers end

			for i=1, n, 1 do
				local name = GetGuildRosterInfo(i + guildOffset);
				current_member = name
				
				local nameText = _G["GuildFrameButton"..i.."Name"]
				local zoneText = _G["GuildFrameButton"..i.."Zone"]
				local levelText = _G["GuildFrameButton"..i.."Level"]
				local classText = _G["GuildFrameButton"..i.."Class"]

				nameText:SetText(strtrim(((self.db.profile.name):gsub(tagpattern, tagreplace)):gsub("%-%s*%-", ''), "- \t"))
				zoneText:SetText(strtrim(((self.db.profile.area):gsub(tagpattern, tagreplace)):gsub("%-%s*%-", ''), "- \t"))
				levelText:SetText(strtrim(((self.db.profile.level):gsub(tagpattern, tagreplace)):gsub("%-%s*%-", ''), "- \t"))
				classText:SetText(strtrim(((self.db.profile.class):gsub(tagpattern, tagreplace)):gsub("%-%s*%-", ''), "- \t"))
				
				-- Make sure we're not overflowing
				if nameText:GetWidth() > 78 then
					nameText:SetJustifyH("LEFT")
					nameText:SetWidth(78)
					nameText:SetHeight(14) -- If we don't set the height, the line wraps.
				end
				if zoneText:GetWidth() > 90 then
					zoneText:SetJustifyH("LEFT")
					zoneText:SetWidth(90)
					zoneText:SetHeight(14) -- If we don't set the height, the line wraps.
				end
				if levelText:GetWidth() > 20 then
					levelText:SetJustifyH("CENTER")
					levelText:SetWidth(20)
					levelText:SetHeight(14) -- If we don't set the height, the line wraps.
				end
				if classText:GetWidth() > 100 then
					classText:SetJustifyH("LEFT")
					classText:SetWidth(100)
					classText:SetHeight(14) -- If we don't set the height, the line wraps.
				end
			end
		end
	end
end

------------------------------------------------------------------------
-- Utility functions
------------------------------------------------------------------------

function GuildList:HowLongAgo(ago)
	if ago then
		local minutes = math.ceil(ago / 60)
		if minutes > 59 then
			local hours = math.ceil(ago / 3600)
			if hours > 23 then
				local days = math.ceil(ago / 86400)
				lastseen = ((days > 1) and INT_GENERAL_DURATION_DAYS_P1 or INT_GENERAL_DURATION_DAYS):format(days)
			else
				lastseen = ((hours > 1) and INT_GENERAL_DURATION_HOURS_P1 or INT_GENERAL_DURATION_HOURS):format(hours)
			end
		else
			lastseen = ((minutes > 1) and INT_GENERAL_DURATION_MIN_P1 or INT_GENERAL_DURATION_MIN):format(minutes)
		end
		return lastseen
	else
		return ""
	end
end

function GuildList:GetRankName(rank, sex)
	--"rank" should be the number of the PVP rank (starts at 5, goes to 19).
	--"sex" should be either MALE or FEMALE.
	return rank > 0 and _G["PVP_RANK_"..rank.."_"..self.faction..((sex == FEMALE) and "_FEMALE" or "")] or ''
end
